<template>
  <CrudLayout>
    <!-- 搜索区域左侧 -->
    <template #search-left>
      <CrudSearchForm v-model="searchParams" :fields="searchFields" @search="handleSearch" @reset="handleSearchReset" />
    </template>

    <!-- 搜索区域右侧 -->
    <template #search-right>
      <CrudButton v-has="config.actions?.add?.permission" type="add" :icon="config.actions?.add?.icon" size="default"
        @click="handleAddRole">
        {{ config.actions?.add?.text ?? '新增' }}
      </CrudButton>
    </template>

    <!-- 表格区域 -->
    <template #table-data>
      <CrudDataTable :data="tableData" :columns="tableColumns" v-loading="loading" :height="tableHeight"
        @selection-change="handleSelectionChange" stripe border />
    </template>

    <!-- 底部左侧 -->
    <template #foot-left>
      <CrudButton v-has="config.actions?.batchDelete?.permission" type="batch-delete"
        :icon="config.actions?.batchDelete?.icon" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
        {{ config.actions?.batchDelete?.text ?? '批量删除' }}
      </CrudButton>
      <span v-if="selectedRows.length > 0" class="selection-info">
        已选择 {{ selectedRows.length }} 项
      </span>
    </template>

    <!-- 底部右侧 -->
    <template #footer-right>
      <CrudPagination v-model:current-page="pagination.current" v-model:page-size="pagination.size"
        :total="pagination.total" :page-sizes="config.pagination?.pageSizes" @size-change="handleSizeChange"
        @current-change="loadTableData" />
    </template>
  </CrudLayout>

  <!-- 弹窗容器 -->
  <div class="dialog-container">
    <!-- 编辑弹窗 -->
    <CrudFormDialog ref="editDialogRef" v-model:visible="editDialogVisible" :title="config.form.editTitle"
      :loading="editSubmitLoading" :form-config="formConfig" :model-value="editFormData"
      @update:model-value="handleEditFormUpdate" @submit="handleEditSubmit" @cancel="handleEditDialogClose" />

    <!-- 新增弹窗 -->
    <CrudFormDialog ref="addDialogRef" v-model:visible="addDialogVisible" :title="config.form.addTitle"
      :loading="addSubmitLoading" :form-config="formConfig" :model-value="addFormData"
      @update:model-value="handleAddFormUpdate" @submit="handleAddSubmit" @cancel="handleAddDialogClose" />

    <!-- 删除确认弹窗 -->
    <CrudConfirmDialog v-model:visible="deleteDialogVisible" :loading="deleteLoading" preset="deleteConfirm"
      :delete-type="deleteType" :target-name="getTargetName(deleteTarget)" :selected-count="selectedRows.length"
      @confirm="confirmDelete" @cancel="handleDeleteDialogClose" />

    <!-- 分配权限抽屉 -->
    <CrudDrawer v-model="permissionDrawerVisible" :title="`分配权限 - ${currentRoleName || ''}`" direction="rtl"
      size="500px" @confirm="confirmAssignPermission" @cancel="closeAssignDrawer">
      <div class="assign-permission" v-loading="permissionDataLoading">
        <div class="assign-permission__header">
          <div class="assign-permission__title">权限分配</div>
          <div class="assign-permission__divider"></div>
        </div>
        <div class="assign-permission__role">
          <span class="assign-permission__role-label">角色：</span>
          <strong class="assign-permission__role-name">{{ currentRoleName }}</strong>
        </div>

        <!-- 权限树形控件 -->
        <div class="assign-permission__controls">
          <el-tree ref="tree" :data="menuArr" show-checkbox node-key="id" default-expand-all
            :default-checked-keys="selectArr" :props="defaultProps" />
        </div>
      </div>
    </CrudDrawer>

  </div>
</template>

<script setup lang="ts">
import type { SearchField } from "@/components/crudstyle/CrudSearchForm/index.vue"
import CrudSearchForm from "@/components/crudstyle/CrudSearchForm/index.vue"
import { ElMessage, type TreeInstance } from "element-plus"
import { computed, onMounted, reactive, ref } from "vue"

import type { TableRowData } from "@/components/cruddata/CrudDataTable/types"
import type { FormConfig } from "@/components/cruddata/CrudFormDialog/types"
import { useUserStore } from '@/stores'
import config from "./config"
import pageApi from "./page.api"
import type { FormData, Pagination, PermissionNode, RoleItem } from "./page.type"

// 获取用户信息
const userStore = useUserStore()

// #region 搜索区域
// 从配置文件中获取搜索字段配置
const searchFields = config.search.fields as SearchField[]

// 搜索参数
const searchParams = ref<Record<string, unknown>>({
  name: '',
})

// 搜索处理
const handleSearch = () => {
  // 重置页码并加载数据
  pagination.current = 1
  loadTableData()
}

// 重置搜索
const handleSearchReset = async () => {
  // 重置为空字符串
  searchParams.value.roleName = ""
  loadTableData()
}

// #endregion

// mount前加载数据
onMounted(async () => {
  await loadTableData()
})

// #region 表格数据
// 表格数据加载中状态
const loading = ref(false)

// 表格数据
const tableData = ref<RoleItem[]>([])

// 表格列配置，添加操作列
const tableColumns = computed(() => {
  const userButtons = userStore.userInfo?.buttons || []

  // 定义所有操作按钮
  const allActions = [
    {
      text: "编辑",
      label: "编辑",
      type: "primary" as const,
      size: "small" as const,
      plain: true,
      icon: "Edit",
      permission: 'btn.Role.update',
      handler: (row: TableRowData) => handleEdit(row as unknown as RoleItem)
    },
    {
      text: "删除",
      label: "删除",
      type: "danger" as const,
      size: "small" as const,
      plain: true,
      icon: "Delete",
      permission: 'btn.Role.remove',
      handler: (row: TableRowData) => handleDelete(row as unknown as RoleItem)
    },
    {
      text: "分配权限",
      label: "分配权限",
      type: "info" as const,
      size: "small" as const,
      plain: true,
      icon: "User",
      permission: 'btn.Role.assign',
      handler: (row: TableRowData) => openAssignDrawer(row as unknown as RoleItem)
    },
  ]

  // 根据权限过滤按钮
  const visibleActions = allActions.filter(action =>
    !action.permission || userButtons.includes(action.permission)
  )

  // 如果没有可见按钮，不显示操作列
  if (visibleActions.length === 0) {
    return config.tableColumns
  }

  return [
    ...config.tableColumns,
    {
      type: "actions",
      label: "操作",
      width: 250,
      align: "center",
      fixed: "right",
      actions: visibleActions
    }
  ]
})

// 加载表格数据
const loadTableData = async () => {
  try {
    loading.value = true
    // 过滤空值
    const params = Object.fromEntries(
      Object.entries(searchParams.value).filter(([, value]) => value !== '' && value !== null && value !== undefined)
    )
    const { data } = await pageApi.getList(pagination.current, pagination.size, params)

    pagination.total = data.data.total
    tableData.value = data.data.records
    ElMessage.success(config.messages?.loadSuccess ?? '加载成功')
  } finally {
    loading.value = false
  }
}

// #endregion

// #region 增删改查（操作列，新增按钮，删除按钮，批量删除按钮）

// 表单配置
const formConfig = reactive<FormConfig>({
  labelWidth: config.form.labelWidth,
  rules: config.form.rules as FormConfig["rules"],
  fields: config.form.fields as FormConfig["fields"]
})

// #region 编辑按钮
// 编辑对话框显示状态
const editDialogVisible = ref(false)

// 编辑对话框引用
const editDialogRef = ref<{ clearValidate: () => void } | null>(null)

// 编辑表单数据
const editFormData = reactive<FormData>({
  id: '',
  name: "",
  description: "",
})

// 编辑按钮提交加载状态
const editSubmitLoading = ref(false)

// 编辑表单数据更新处理
const handleEditFormUpdate = (value: FormData) => {
  Object.assign(editFormData, value)
}

// 编辑按钮点击
const handleEdit = (row: RoleItem): void => {
  Object.assign(editFormData, row)
  editDialogVisible.value = true
}

// 编辑弹窗确认
const handleEditSubmit = async () => {
  editSubmitLoading.value = true
  try {
    await pageApi.update(editFormData)
    ElMessage.success(config.messages?.editSuccess ?? "修改成功！")
    await loadTableData()
  } finally {
    handleEditDialogClose()
    editSubmitLoading.value = false
  }
}

// 编辑弹窗关闭
const handleEditDialogClose = () => {
  editDialogVisible.value = false
  Object.keys(editFormData).forEach(key => {
    delete (editFormData as Record<string, unknown>)[key]
  })
  editDialogRef.value?.clearValidate()
}

// #endregion

// #region 新增按钮
// 新增对话框显示状态
const addDialogVisible = ref(false)

// 新增对话框引用
const addDialogRef = ref<{ clearValidate: () => void } | null>(null)

// 新增表单数据
const addFormData = reactive<FormData>({
  name: "",
  description: "",
})

// 对话框提交加载状态
const addSubmitLoading = ref(false)

// 新增表单数据更新处理
const handleAddFormUpdate = (value: FormData) => {
  Object.assign(addFormData, value)
}

// 新增按钮点击
const handleAddRole = () => {
  // 清空表单数据
  Object.assign(addFormData, {
    name: "",
    description: "",
  })
  addDialogVisible.value = true
}

// 新增弹窗确认
const handleAddSubmit = async () => {
  addSubmitLoading.value = true
  try {
    pagination.current = 1
    await pageApi.create(addFormData)
    ElMessage.success(config.messages?.addSuccess ?? "添加成功！")
    await loadTableData()
  } finally {
    handleAddDialogClose()
    addSubmitLoading.value = false
  }
}

// 新增弹窗关闭
const handleAddDialogClose = () => {
  addDialogVisible.value = false
  Object.keys(addFormData).forEach(key => {
    delete (addFormData as Record<string, unknown>)[key]
  })
  addDialogRef.value?.clearValidate()
}

// #endregion

// #region 删除按钮

// 删除确认对话框相关状态
const deleteDialogVisible = ref(false)
const deleteLoading = ref(false)
const deleteType = ref<"single" | "batch">("single")
const deleteTarget = ref<RoleItem | null>(null)
const selectedRows = ref<RoleItem[]>([])

// 获取删除目标名称
const getTargetName = (target: unknown): string => {
  if (!target || !config.page.targetNameField) {
    return ""
  }
  return (target as unknown as Record<string, unknown>)[config.page.targetNameField] as string || ""
}

// 删除按钮
// 单个删除
const handleDelete = (row: RoleItem): void => {
  deleteType.value = "single"
  deleteTarget.value = row
  deleteDialogVisible.value = true
}

// 批量删除
const handleBatchDelete = (): void => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请选择要删除的数据")
    return
  }

  deleteType.value = "batch"
  deleteTarget.value = null
  deleteDialogVisible.value = true
}

// 弹窗取消按钮
const handleDeleteDialogClose = (): void => {
  deleteDialogVisible.value = false
  deleteTarget.value = null
  deleteLoading.value = false
}

// 弹窗确认删除按钮
const confirmDelete = async (): Promise<void> => {
  deleteLoading.value = true
  try {
    if (deleteType.value === "single") {
      // 单个删除
      if (!deleteTarget.value) {
        ElMessage.error("删除目标不存在")
        return
      }
      await pageApi.delete(deleteTarget.value.id as string)
      ElMessage.success("删除成功")
    } else {
      // 批量删除
      if (selectedRows.value.length === 0) {
        ElMessage.error("请选择要删除的数据")
        return
      }
      await pageApi.batchDelete(selectedRows.value.map(row => row.id as string))
      ElMessage.success("批量删除成功")
      selectedRows.value = []
    }
    loadTableData()
  } finally {
    handleDeleteDialogClose()
    deleteLoading.value = false
  }
}

// 处理表格选择列变化
const handleSelectionChange = (selection: TableRowData[]): void => {
  selectedRows.value = selection as unknown as RoleItem[]
  console.log("选中的数据:", selection)
}

// #endregion

// #region 分配权限按钮

// 权限抽屉相关状态
const permissionDrawerVisible = ref(false)
const permissionDataLoading = ref(false)
const currentRoleName = ref("")
const currentRoleId = ref<string | null>(null)
const menuArr = ref<PermissionNode[]>([])
const selectArr = ref<string[]>([])
const tree = ref<TreeInstance | null>(null)

// 树形控件配置
const defaultProps = {
  children: "children",
  label: "name",
}

// 打开分配权限抽屉
const openAssignDrawer = async (row: RoleItem): Promise<void> => {
  currentRoleName.value = row.name
  permissionDrawerVisible.value = true
  permissionDataLoading.value = true

  try {
    // 获取角色权限数据
    currentRoleId.value = row.id as string
    const { data } = await pageApi.getRolePermission(row.id as string)
    const assignData = data.data as unknown as { allPermission: PermissionNode[], assignPermission: string[] }
    menuArr.value = assignData.allPermission
    selectArr.value = assignData.assignPermission || []

  } catch (error) {
    console.error("获取权限数据失败:", error)
    ElMessage.error("获取权限数据失败")
  } finally {
    permissionDataLoading.value = false
  }
}

// 关闭分配权限抽屉
const closeAssignDrawer = (): void => {
  permissionDrawerVisible.value = false
  currentRoleName.value = ""
  menuArr.value = []
  selectArr.value = []
}

// 确认分配权限
const confirmAssignPermission = async (): Promise<void> => {
  if (!currentRoleName.value) return

  try {
    permissionDataLoading.value = true

    // 获取选中节点和半选节点的ID
    if (!tree.value) {
      ElMessage.error('权限树未初始化')
      return
    }
    const checkedKeys = tree.value.getCheckedKeys()
    const halfCheckedKeys = tree.value.getHalfCheckedKeys()
    // 将 TreeKey 转换为 string 类型
    const allPermissionIds = [...checkedKeys, ...halfCheckedKeys].map(key => String(key))

    // 调用API分配权限
    await pageApi.assignPermission(currentRoleId.value as string, allPermissionIds)

    ElMessage.success("权限分配成功")
    closeAssignDrawer()

    // 刷新页面以更新权限
    // window.location.reload()
  } catch (error) {
    console.error("分配权限失败:", error)
    ElMessage.error("分配权限失败")
  } finally {
    permissionDataLoading.value = false
  }
}


// #endregion

// #region 底部分页组件

// 分页信息
const pagination = reactive<Pagination>({
  current: 1,
  size: config.pagination?.defaultPageSize || 10,
  total: 0,
  pages: 0
})

// 处理页面展示数据数量size变化
const handleSizeChange = (): void => {
  pagination.current = 1
  loadTableData()
}

// #endregion

// #region 其他通用函数

// 计算表格高度
const tableHeight = computed(() => {
  const pageHeight = window.innerHeight - 64 - 48
  const searchSectionHeight = 80
  const tableFooterHeight = 61
  const reservedHeight = 10
  const calculatedHeight = pageHeight - searchSectionHeight - tableFooterHeight - reservedHeight
  const finalHeight = Math.max(calculatedHeight, 300)
  return `${finalHeight}px`
})

// #endregion
</script>

<style scoped lang="scss">
.selection-info {
  margin-left: 12px;
  color: $text-color-secondary;
  font-size: $home-font-size-normal;
}

/* 分配权限抽屉样式 */
.assign-permission {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.assign-permission__header {
  margin-bottom: 24px;
}

.assign-permission__title {
  font-size: $home-font-size-medium;
  font-weight: 600;
  color: $text-color-primary;
  margin-bottom: 12px;
}

.assign-permission__divider {
  height: 2px;
  background: linear-gradient(to right, var(--primary-color, $primary-color), transparent);
  border-radius: 1px;
}

.assign-permission__role {
  display: flex;
  align-items: center;
  padding: 16px;
  background: $bg-color-light;
  border-radius: 8px;
  margin-bottom: 20px;
  border-left: 3px solid var(--primary-color, $primary-color);
  transition: all 0.3s ease;

  &:hover {
    background: $hover-bg-light;
    transform: translateX(2px);
  }

  &-label {
    color: $text-color-secondary;
    font-size: $home-font-size-normal;
  }

  &-name {
    color: var(--primary-color, $primary-color);
    font-size: 15px;
    margin-left: 4px;
    font-weight: 500;
  }
}

.assign-permission__controls {
  margin-bottom: 16px;
  padding: 16px;
  background: white;
  border: 1px solid $border-color-base;
  border-radius: 8px;
  transition: all 0.3s ease;

  &:hover {
    border-color: var(--primary-color-hover, $primary-color-hover);
    box-shadow: 0 2px 8px var(--primary-color-alpha-10, rgba(96, 122, 251, 0.1));
  }

  .el-tree {
    max-height: 500px;
    overflow-y: auto;

    /* 树节点hover效果 */
    :deep(.el-tree-node) {
      &:hover {
        .el-tree-node__content {
          background-color: $hover-bg-light;
          border-radius: 4px;
        }
      }
    }

    /* 树节点内容区域 */
    :deep(.el-tree-node__content) {
      height: 36px;
      border-radius: 4px;
      transition: all 0.2s ease;

      &:hover {
        background-color: $hover-bg-light;
      }
    }

    /* 树节点展开图标 */
    :deep(.el-tree-node__expand-icon) {
      color: $text-color-secondary;
      transition: all 0.2s ease;

      &.expanded {
        color: var(--primary-color, $primary-color);
      }
    }

    /* 当前选中节点的样式 */
    :deep(.el-tree-node.is-current) {
      .el-tree-node__content {
        background-color: var(--primary-color-alpha-10, $primary-color-alpha-10);
        border-radius: 4px;

        .el-tree-node__label {
          color: var(--primary-color, $primary-color);
          font-weight: 500;
        }
      }
    }

    /* 树节点标签样式 */
    :deep(.el-tree-node__label) {
      color: $text-color-primary;
      font-size: 14px;
      transition: color 0.2s ease;
    }

    /* 复选框样式美化 */
    :deep(.el-checkbox) {
      margin-right: 0;
      padding: 8px 4px;
      border-radius: 6px;
      transition: all 0.2s ease;

      &:hover {
        background-color: $hover-bg-light;
      }

      // &.is-checked {
      //   background-color: var(--primary-color-alpha-10, $primary-color-alpha-10);
      // }
    }

    /* 复选框选中颜色为主题色 */
    :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
      background-color: var(--primary-color, $primary-color);
      border-color: var(--primary-color, $primary-color);
    }

    :deep(.el-checkbox__input.is-indeterminate .el-checkbox__inner) {
      background-color: var(--primary-color, $primary-color);
      border-color: var(--primary-color, $primary-color);
    }

    :deep(.el-checkbox__input.is-checked .el-checkbox__inner::after) {
      border-color: #fff;
    }

    :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
      border-color: var(--primary-color, $primary-color);
    }

    :deep(.el-checkbox__input:hover .el-checkbox__inner) {
      border-color: var(--primary-color-hover, $primary-color-hover);
    }

    /* 复选框文字颜色 */
    :deep(.el-checkbox.is-checked .el-checkbox__label) {
      color: var(--primary-color, $primary-color);
      font-weight: 500;
    }

    :deep(.el-checkbox:hover .el-checkbox__label) {
      color: var(--primary-color-hover, $primary-color-hover);
    }

    :deep(.el-checkbox__label) {
      color: $text-color-primary;
      transition: color 0.2s ease;
    }

    /* 自定义节点样式 */
    .custom-tree-node {
      display: flex;
      align-items: center;
      flex: 1;
      padding: 0 4px;

      .node-label {
        margin-right: 8px;
        font-weight: 500;
      }

      .node-code {
        margin-right: 8px;
        padding: 2px 6px;
        background: $bg-color-light;
        border-radius: 3px;
        font-size: 12px;
        color: $text-color-secondary;
        font-family: monospace;
      }

      .node-type {
        margin-left: auto;
        padding: 2px 6px;
        background: #e8f4fd;
        color: #1890ff;
        border-radius: 3px;
        font-size: 12px;
      }
    }
  }
}

/* 权限树滚动条美化 */
.assign-permission__controls .el-tree {
  &::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }

  &::-webkit-scrollbar-track {
    background: $bg-color-light;
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: $border-color-light;
    border-radius: 3px;

    &:hover {
      background: $text-color-placeholder;
    }
  }
}

/* 过渡动画 */
.assign-permission {
  * {
    transition: all 0.2s ease;
  }
}

.permission-tree {
  height: calc(100vh - 300px);
  overflow-y: auto;
}

/* 暗黑模式适配 */
@media (prefers-color-scheme: dark) {
  .assign-permission__title {
    color: $text-color-primary-dark;
  }

  .assign-permission__role {
    background: $bg-color-gray-dark;
    border-left-color: var(--primary-color, $primary-color);

    &:hover {
      background: $hover-bg-light-dark;
    }

    &-label {
      color: $text-color-secondary-dark;
    }

    &-name {
      color: var(--primary-color, $primary-color);
    }
  }

  .assign-permission__controls {
    background: $bg-color-card-dark;
    border-color: $border-color-base-dark;

    &:hover {
      border-color: var(--primary-color-hover, $primary-color-hover);
      box-shadow: 0 2px 8px var(--primary-color-alpha-20, rgba(96, 122, 251, 0.2));
    }

    .el-tree {

      /* 树节点hover效果 */
      :deep(.el-tree-node) {
        &:hover {
          .el-tree-node__content {
            background-color: $hover-bg-light-dark;
          }
        }
      }

      /* 树节点内容区域 */
      :deep(.el-tree-node__content) {
        &:hover {
          background-color: $hover-bg-light-dark;
        }
      }

      /* 树节点展开图标 */
      :deep(.el-tree-node__expand-icon) {
        color: $text-color-secondary-dark;

        &.expanded {
          color: var(--primary-color, $primary-color);
        }
      }

      /* 当前选中节点的样式 */
      :deep(.el-tree-node.is-current) {
        .el-tree-node__content {
          background-color: $active-bg-primary-dark;
        }

        .el-tree-node__label {
          color: var(--primary-color, $primary-color);
        }
      }

      /* 树节点标签样式 */
      :deep(.el-tree-node__label) {
        color: $text-color-primary-dark;
      }

      /* 复选框样式美化 */
      :deep(.el-checkbox) {
        &:hover {
          background-color: $hover-bg-light-dark;
        }

        &.is-checked {
          background-color: $active-bg-primary-dark;
        }
      }

      /* 复选框选中颜色为主题色 */
      :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
        background-color: var(--primary-color, $primary-color);
        border-color: var(--primary-color, $primary-color);
      }

      :deep(.el-checkbox__input.is-indeterminate .el-checkbox__inner) {
        background-color: var(--primary-color, $primary-color);
        border-color: var(--primary-color, $primary-color);
      }

      :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
        border-color: var(--primary-color, $primary-color);
      }

      :deep(.el-checkbox__input:hover .el-checkbox__inner) {
        border-color: var(--primary-color-hover, $primary-color-hover);
      }

      /* 复选框文字颜色 */
      :deep(.el-checkbox.is-checked .el-checkbox__label) {
        color: var(--primary-color, $primary-color);
      }

      :deep(.el-checkbox:hover .el-checkbox__label) {
        color: var(--primary-color-hover, $primary-color-hover);
      }

      :deep(.el-checkbox__label) {
        color: $text-color-primary-dark;
      }

      /* 自定义节点样式 */
      .custom-tree-node {
        .node-code {
          background: $bg-color-gray-dark;
          color: $text-color-secondary-dark;
        }

        .node-type {
          background: var(--primary-color-alpha-20, rgba(96, 122, 251, 0.2));
          color: var(--primary-color, $primary-color);
        }
      }
    }
  }

  /* 权限树滚动条美化 */
  .assign-permission__controls .el-tree {
    &::-webkit-scrollbar-track {
      background: $bg-color-gray-dark;
    }

    &::-webkit-scrollbar-thumb {
      background: $border-color-base-dark;

      &:hover {
        background: $dark-text-color-disabled;
      }
    }
  }

  .selection-info {
    color: $text-color-secondary-dark;
  }
}
</style>
